package com.zoe.onelink.feign.interceptor;

import com.zoe.onelink.common.constant.RpcClient;
import com.zoe.onelink.common.constant.RpcConstant;
import com.zoe.onelink.common.entity.ResultVO;
import com.zoe.onelink.core.exception.interceptor.WebExceptionInterceptor;
import com.zoe.onelink.util.StackTraceUtil;
import feign.codec.DecodeException;
import lombok.RequiredArgsConstructor;
import org.springframework.core.annotation.Order;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * <p>标题: </p>
 * <p>描述: </p>
 * <p>版权: Copyright (c) 2021</p>
 * <p>公司: 智业软件股份有限公司</p>
 *
 * @version: 1.0
 * @author: ruansheng
 * @date: 2021-12-16
 */
@Order(20000)
@RequiredArgsConstructor
public class FeignExceptionInterceptor implements WebExceptionInterceptor {

    private final HttpServletRequest httpServerRequest;
    private final HttpServletResponse httpServletResponse;

    @Override
    public Exception beforeHandle(Exception ex) {
        if (this.isFeignProvider()) {
            StackTraceElement[] filteredStackTraces = StackTraceUtil.cutStackTrace(ex.getStackTrace(), StackTraceUtil.ONELINK_STACK_TRACE_CLASS_NAME_PREFIX_SET, true);
            ex.setStackTrace(filteredStackTraces);
            return ex;
        } else if (!(ex instanceof DecodeException)) {
            return ex;
        }
        Throwable cause = ex.getCause();
        if (cause == null) {
            return ex;
        }
        return (Exception) cause;
    }

    @Override
    public Exception afterHandle(Exception ex, ResultVO<Object> resultVO) {
        if (this.isFeignProvider()) {
            // 内部Feign调用统一使用ApiException封装,所以状态码应该是200
            this.httpServletResponse.setStatus(HttpServletResponse.SC_OK);
        }
        return ex;
    }

    /**
     * 是否是feign调用
     *
     * @return true: 当前是提供者, false: 当前是消费者
     */
    protected boolean isFeignProvider() {
        String endpoint = this.httpServerRequest.getHeader(RpcConstant.RPC_CLIENT_HEADER_NAME);
        return RpcClient.FEIGN.name().equals(endpoint);
    }

}
